// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Tools.cpp 182 2007-11-08 15:17:32Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Triangulations_3/Py_Tools.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================


// include ====================================================================
#include <CGAL/basic.h>
#include <include/Kernels.h>
#include <CGAL/Triangulation_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_3.h>
#include <CGAL/Alpha_shape_vertex_base_3.h>
#include <CGAL/Alpha_shape_cell_base_3.h>

#include <boost/python.hpp>
#include <boost/cstdint.hpp>
#include <include/iterator.h>
#include <list>
#include <iostream>

using boost::python::object;

//BEGIN functions of Vertex Class ========================================
template <class Vertex_handle> 
object point(const Vertex_handle& vh)
{
	return object(vh->point());
}
template <class Vertex_handle> 
object py_info(const Vertex_handle& vh)
{
	return object(vh->info());
}
template <class Vertex_handle> 
void set_info(Vertex_handle& vh,const object& py_obj)
{
	vh->info() = py_obj;
}
template <class Vertex_handle,class Point> 
void set_point(Vertex_handle& vh,const Point& pt)
{
	vh->set_point(pt);
}
template <class Vertex_handle> 
bool is_valid(const Vertex_handle& vh)
{
	return vh->is_valid();
}
//==================

template <class Vertex_handle,class Cell_handle> 
Cell_handle cell(const Vertex_handle& vh)
{
	return vh->cell();
}
//==================

template <class Vertex_handle,class Cell_handle> 
void set_cell(const Vertex_handle& vh,Cell_handle c)
{
	return vh->set_cell(c);
}
//END of Vertex functions ================================================

//BEGIN================== equivalent to expoting of '->' operator of Cell_handle =====================

template <class Cell_handle,class Vertex_handle> 
Vertex_handle py_vertex(const Cell_handle& ch,int i)
{
	return ch->vertex(i);
}
//===========================

template <class Cell_handle,class Vertex_handle> 
bool py_has_vertex1(const Cell_handle& ch,Vertex_handle v)
{
	return ch->has_vertex(v);
}
//===========================

template <class Cell_handle,class Vertex_handle> 
bool py_has_vertex2(const Cell_handle& ch,Vertex_handle v,int& i)
{
	return ch->has_vertex(v,i);
}
//===========================

template <class Cell_handle,class Vertex_handle> 
int py_vertex_index(const Cell_handle& ch,Vertex_handle v)
{
	return ch->index(v);
}
//===========================

template <class Cell_handle,class Cell_or_Vertex_handle> 
int py_cell_index(const Cell_handle& ch,Cell_or_Vertex_handle c)
{
	return ch->index(c);
}
//===========================

template <class Cell_handle> 
Cell_handle py_neighbor(const Cell_handle& ch,int i)
{
	return ch->neighbor(i);
}
//===========================

template <class Cell_handle> 
bool py_has_neighbor1(const Cell_handle& ch,Cell_handle c)
{
	return ch->has_neighbor(c);
}
//===========================

template <class Cell_handle> 
bool py_has_neighbor2(const Cell_handle& ch,Cell_handle c,int& i)
{
	return ch->has_neighbor(c,i);
}
//===========================

template <class Cell_handle,class Vertex_handle> 
void py_set_vertices(Cell_handle& ch,Vertex_handle v0,Vertex_handle v1,Vertex_handle v2,Vertex_handle v3)
{
	ch->set_vertices(v0,v1,v2,v3);
}
//===========================

template <class Cell_handle,class Vertex_handle> 
void py_set_vertex(Cell_handle& ch,int i,Vertex_handle v)
{
	ch->set_vertex(i,v);
}
//===========================

template <class Cell_handle> 
void py_set_neighbor(Cell_handle& ch,int i,Cell_handle n)
{
	ch->set_neighbor(i,n);
}
//===========================

template <class Cell_handle> 
void py_set_neighbors(Cell_handle& ch,Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3)
{
	ch->set_neighbors(n0,n1,n2,n3);
}
//===========================

//END================== equivalent to expoting of '->' operator of Cell_handle =====================

template<typename T>
object py_first(const T& t)
{
	return object(t.first);
}
template<typename T>
object py_second(const T& t)
{
  return object(t.second);
}
template<typename T>
object py_third(const T& t)
{
  return object(t.third);
}
//=======================
template <typename T>
object py_indice(const T& edge,int i)
{
	switch(i)
	{
		case 0: return object(edge.second);
		case 1: return object(edge.third);
		default: std::cout<<"precondition: 0 <= i <= 1 "<< std::endl;
	}
	return object();
}
//=======================================
//exporting tools of Triangulations.========================
template <class kernel > 
void Py_Tools_3()
{
	using namespace boost::python;
	typedef CGAL::Alpha_shape_vertex_base_3<kernel>         Avb;
	typedef CGAL::Triangulation_vertex_base_with_info_3<boost::python::object,kernel,Avb> 	Vb;

	typedef CGAL::Alpha_shape_cell_base_3<kernel>           Fb;
	typedef CGAL::Triangulation_data_structure_3<Vb,Fb> 	Tds;

	typedef CGAL::Triangulation_3<kernel,Tds>   				Triangulation_3;

	typedef typename Triangulation_3::Finite_facets_iterator 	Finite_facets_iterator;
	typedef typename Triangulation_3::Facet_circulator			Facet_circulator;
	typedef typename Triangulation_3::All_facets_iterator 	    All_facets_iterator;
	typedef typename Triangulation_3::Cell_handle 				Cell_handle;

	typedef typename kernel::Point_3 							Point_3;
	typedef typename Triangulation_3::Point_iterator 			Point_iterator;

	typedef typename Triangulation_3::Vertex_handle 			Vertex_handle;
	typedef typename Triangulation_3::Finite_vertices_iterator 	Finite_vertices_iterator;
	typedef typename Triangulation_3::All_vertices_iterator 	All_vertices_iterator;

	typedef typename Triangulation_3::Finite_edges_iterator		Finite_edges_iterator;
	typedef typename Triangulation_3::All_edges_iterator		All_edges_iterator;

	typedef typename Triangulation_3::Locate_type 				Locate_type;
	typedef typename kernel::Segment_3 							Segment_3;
	typedef typename kernel::Triangle_3 						Triangle;

	typedef typename CGAL::Triple<Cell_handle, int, int> 	Edge;
	typedef typename std::pair<Cell_handle, int> 			Facet;

const char*  Vertex_doc[]={
"	This Class corresponds to the Vertex_handle of cgal's C++ concept, \n\
	it's not used directly, but returned by many functions of the Trinagulation \n\
	classes like in the insertion of points",\
"	v.point( self) -> Point_3\n\
 	 Returns the point.\n",\
"	v.set_point( self , Point_3 p) -> Sets the point.\n",
"	Returns the object stored in the vertex.\n",\
"	sets the info of Vertex, the info type could be any python object\n",\
"	v.is_valid( self, bool verbose = False) ->bool\n\
	Performs any desired test on a vertex. \n\
	Checks that the pointer to an incident cell is not the default constructed handle.\n",\
"	v.cell( self) -> Cell\n\
	Returns the incident cell\n",\
"	v.set_cell( self, Cell c) -> Sets the incident cell\n"

};
	class_<Vertex_handle>("Vertex",Vertex_doc[0],init<>())
		.def("point",&point<Vertex_handle>,Vertex_doc[1])
		.def("set_point",&set_point<Vertex_handle,Point_3>,Vertex_doc[2])
		.def("info",&py_info<Vertex_handle>,Vertex_doc[3])
		.def("set_info",&set_info<Vertex_handle>,Vertex_doc[4])
		.def("is_valid",&is_valid<Vertex_handle>,Vertex_doc[5])
		.def("cell",&cell<Vertex_handle,Cell_handle>,Vertex_doc[6])
		.def("set_cell",&set_cell<Vertex_handle,Cell_handle>,Vertex_doc[7])
		.def(self==self)
		.def(self!=self)
		.def(self < self)
	;

const char*  Cell_doc[]={
"	This Class corresponds to the Cell_handle of cgal's C++ concept, \n\
	it's not used directly, but related to the Trinagulations\n",\

"	c.vertex( self ,int i) -> Vertex\n\
	Returns the vertex i of c.\n\
	Precondition: i belongs to {0, 1, 2, 3}.\n",\

"	c.vertex_index( self ,Vertex v) -> int \n\
	Returns the index of v.\n\
	Precondition: v is a vertex of c\n",\

"	c.has_vertex( self ,Vertex v) -> bool\n\
	True iff v is a vertex of c.\n",\

"	c.neighbor( self ,int i) -> Cell\n\
	Returns the neighbor i of c.\n\
	Precondition: i belongs {0, 1, 2, 3}.\n",\

"	c.index( self , Cell n) -> int \n\
	Returns the index of cell n in c.\n\
	Precondition: n is a neighbor of c.\n\n\
	c.index( self , Vertex v) -> int \n\
	Returns the index of cell v in c.",\

"	c.has_neighbor( self ,Cell n) -> bool\n\
	Returns true if n is a neighbor of c.\n",\

"	c.set_vertex( self ,int i, Vertex v) -> Sets vertex i to v.\n\
	Precondition: i belongs to {0, 1, 2, 3}.\n",\

"	c.set_vertices( self) -> Sets the vertices to the default constructed Cell.\n",\

"	c.set_neighbor( self ,int i, Cell n) -> Sets neighbor i to n.\n\
	Precondition: i belongs to {0, 1, 2, 3}.\n",\

"	c.set_neighbors( self) -> Sets the neighbors to the default constructed handle.\n",\

"	c.is_valid ( self ,bool verbose = false) -> bool\n\
	Performs any desired geometric test on a cell.\n\
	When verbose is set to true, messages are printed to give a precise indication of the kind of invalidity encountered.\n"



};
	// Cell_handle Class.
	class_<Cell_handle>("Cell",Cell_doc[0],init<>())
		.def("vertex",&py_vertex<Cell_handle,Vertex_handle>,Cell_doc[1])
		.def("vertex_index",&py_vertex_index<Cell_handle,Vertex_handle>,Cell_doc[2])
		.def("has_vertex",&py_has_vertex1<Cell_handle,Vertex_handle>,Cell_doc[3])
// 		.def("has_vertex",&py_has_vertex2<Cell_handle,Vertex_handle>)
		.def("neighbor",&py_neighbor<Cell_handle>,Cell_doc[4])
		.def("index",&py_cell_index<Cell_handle,Cell_handle>,Cell_doc[5])
		.def("index",&py_cell_index<Cell_handle,Vertex_handle>)
		.def("has_neighbor",&py_has_neighbor1<Cell_handle>,Cell_doc[6])
// 		.def("has_neighbor",&py_has_neighbor2<Cell_handle>)
		.def("set_vertex",&py_set_vertex<Cell_handle,Vertex_handle>,Cell_doc[7])
		.def("set_vertices",&py_set_vertices<Cell_handle,Vertex_handle>,Cell_doc[8])
		.def("set_neighbor",&py_set_neighbor<Cell_handle>,Cell_doc[9])
		.def("set_neighbors",&py_set_neighbors<Cell_handle>,Cell_doc[10])
		.def(self==self)
		.def(self!=self)
		.def(self < self)
	;
	class_<Edge>("Edge",init<>())
		.def(init< const Cell_handle&,int,int >())
		.def("cell",&py_first<Edge>,"e.cell( Self) -> Cell\nReturns the cell of the Edge e\n")
 		.def("index",&py_indice<Edge>,"e.index( self ,int i) -> int\nReturns the indices of the Edge e\nPrecondition: i belongs to {0,1}\n")
		.def(self==self)
	;
	class_<Facet>("Facet",init<>())
		.def(init< const Cell_handle&,int>())
		.def("cell",&py_first<Facet>,"f.cell( Self) -> Cell\nReturns the cell of the facet f\n")
 		.def("vertex_index",&py_second<Facet>,"e.vertex_index( self ) -> int\nReturns the vertex index of the facet f\n")
		.def(self==self)
		.def(self!=self)
	;
}

extern void export_Triangulation_vertex_base_with_info_2();

void export_Tools_3()
{
	Py_Tools_3<K>();
}
